package com.yzh.luckydraw.domain.activity.service.partake.impl;

import com.yzh.dbrouter.strategy.IDBRouterStrategy;
import com.yzh.luckydraw.common.Constants;
import com.yzh.luckydraw.common.Result;
import com.yzh.luckydraw.domain.activity.model.req.PartakeReq;
import com.yzh.luckydraw.domain.activity.model.res.StockResult;
import com.yzh.luckydraw.domain.activity.model.vo.*;
import com.yzh.luckydraw.domain.activity.repository.IActivityRepository;
import com.yzh.luckydraw.domain.activity.repository.IUserTakeActivityRepository;
import com.yzh.luckydraw.domain.activity.service.partake.BaseActivityPartake;
import com.yzh.luckydraw.domain.supports.ids.IIdGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class ActivityPartakeImpl extends BaseActivityPartake {
    private Logger logger = LoggerFactory.getLogger(ActivityPartakeImpl.class);
    @Resource
    private IDBRouterStrategy dbRouter;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private IUserTakeActivityRepository userTakeActivityRepository;

    @Override
    protected UserTakeActivityVO queryNoConsumedTakeActivityOrder(Long activity, String uId) {
        return userTakeActivityRepository.queryNoConsumedTakeActivityOrder(activity, uId);
    }

    @Override
    public Result checkActivityBill(PartakeReq partakeReq, ActivityBillVO billVO) {
        //校验活动状态
        if (!billVO.getState().equals(Constants.ActivityState.DOING.getCode())) {
            logger.warn("活动当前状态非可用 state：{}", billVO.getState());
            return Result.buildErrorResult("非可用活动状态");
        }
        //校验活动日期
        //after：beginTime < partakeDate -> false
        if (billVO.getBeginTime().after(partakeReq.getPartakeDate()) || billVO.getEndTime().before(partakeReq.getPartakeDate())) {
            logger.warn("活动时间范围非可用 beginDateTime：{} endDateTime：{}", billVO.getBeginTime(), billVO.getEndTime());
            return Result.buildErrorResult("非可用活动时间");
        }
        //校验活动库存
        if (billVO.getStockSurplusCount() <= 0) {
            logger.warn("活动剩余库存非可用 stockSurplusCount：{}", billVO.getStockSurplusCount());
            return Result.buildErrorResult("库存不足");
        }
        //校验个人剩余次数，这里leftCount可能为空，所以要校验。它若是空，说明是第一次领取，在仓储层会初始化它的值
        if (billVO.getUserTakeLeftCount() != null && billVO.getUserTakeLeftCount() <= 0) {
            logger.warn("个人领取次数非可用 userTakeLeftCount：{}", billVO.getUserTakeLeftCount());
            return Result.buildErrorResult("个人可领取次数不足");
        }
        return Result.buildSuccessResult();
    }

    @Override
    public Result subtractionActivityStock(PartakeReq partakeReq) {
        int count = activityRepository.subtractionActivityStock(partakeReq.getActivityId());
        if (count == 0) {
            logger.error("扣减活动库存失败 activityId：{}", partakeReq.getActivityId());
            return Result.buildResult(Constants.ResponseCode.NO_UPDATE);
        }
        return Result.buildSuccessResult();
    }

    @Override
    protected StockResult subtractionActivityStockByRedis(String uId, Long activityId, Integer stockCount, Date endTime) {
        return activityRepository.subtractionActivityStockByRedis(uId, activityId, stockCount, endTime);
    }

    @Override
    protected void recoverActivityCacheStockByRedis(Long activityId, String tokenKey, String code) {
        activityRepository.recoverActivityCacheStockByRedis(activityId, tokenKey, code);
    }

    @Override
    public Result grabActivity(PartakeReq req, ActivityBillVO billVO, Long takeId) {
        try {
            //手动分库
            dbRouter.dbRouter(req.getuId());
            //调用事务(路由组件中以实现事务规则)
            return transactionTemplate.execute(status -> {
                try {
                    //更新user_take_activity_count表的领取次数信息
                    int updateCount = userTakeActivityRepository.subtractionLeftCount(billVO.getActivityId(), billVO.getActivityName(), billVO.getTakeCount(), billVO.getUserTakeLeftCount(), billVO.getuId(), req.getPartakeDate());
                    //SQL无结果，回滚事务
                    if (updateCount == 0) {
                        status.setRollbackOnly();
                        logger.error("领取活动，扣减个人已参与次数失败 activityId：{} uId：{}", req.getActivityId(), req.getuId());
                        return Result.buildResult(Constants.ResponseCode.NO_UPDATE);
                    }
                    //user_take_activity表插入领取活动信息
                    userTakeActivityRepository.takeActivity(billVO.getActivityId(), billVO.getActivityName(), billVO.getStrategyId(), billVO.getTakeCount(), billVO.getUserTakeLeftCount(), billVO.getuId(), req.getPartakeDate(), takeId);
                } catch (Exception e) {
                    status.setRollbackOnly();
                    logger.error("领取活动，唯一索引冲突 activityId：{} uId：{}", req.getActivityId(), req.getuId(), e);
                    return Result.buildResult(Constants.ResponseCode.INDEX_DUP);
                }
                return Result.buildSuccessResult();
            });
        } finally {
            dbRouter.clear();
        }

    }

    @Override
    public Result recordDrawOrder(DrawOrderVO drawOrderVO) {
        try {
            dbRouter.dbRouter(drawOrderVO.getuId());
            return transactionTemplate.execute(status -> {
                try {
                    //锁定活动领取记录
                    int lockTackActivityResult = userTakeActivityRepository.lockTackActivity(drawOrderVO.getuId(), drawOrderVO.getActivityId(), drawOrderVO.getTakeId());
                    if (lockTackActivityResult == 0) {
                        status.setRollbackOnly();
                        logger.error("记录中奖单，个人参与活动抽奖已消耗完 activityId：{} uId：{}", drawOrderVO.getActivityId(), drawOrderVO.getuId());
                        return Result.buildResult(Constants.ResponseCode.NO_UPDATE);
                    }
                    //保存抽奖信息
                    userTakeActivityRepository.saveUserStrategyExport(drawOrderVO);
                } catch (Exception e) {
                    status.setRollbackOnly();
                    logger.error("记录中奖单，唯一索引冲突 activityId：{} uId：{}", drawOrderVO.getActivityId(), drawOrderVO.getuId(), e);
                    return Result.buildResult(Constants.ResponseCode.INDEX_DUP);
                }
                return Result.buildSuccessResult();
            });
        } finally {
            dbRouter.clear();
        }
    }

    @Override
    public void updateInvoiceMqState(String uId, Long orderId, Integer mqState) {
        userTakeActivityRepository.updateInvoiceMqState(uId, orderId, mqState);
    }

    @Override
    public List<InvoiceVO> scanInvoiceMqState(int db, int tb) {
        try {
            //设置路由
            dbRouter.setDBKey(db);
            dbRouter.setTBKey(tb);
            //查询数据
            return userTakeActivityRepository.scanInvoiceMqState();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            dbRouter.clear();
        }
    }

    @Override
    public void updateActivityStock(ActivityPartakeRecordVO activityPartakeRecordVO) {
        userTakeActivityRepository.updateActivityStock(activityPartakeRecordVO);
    }
}
